﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;
using System.Windows.Forms;

//adding libraries for handling word documents.
using Word = Microsoft.Office.Interop.Word;
using System.Reflection;
using System.Runtime.InteropServices;

namespace AssetManagementSystem.Model.Agreement {
    public static class DocumentAssistant {

        private static Random random;
        private static object o;
        private static object oFalse;
        private static object oTrue;

        private static Word._Application app = null;
        private static Word.Documents docs = null;
        private static Word.Document doc = null;

        private const string DOC_TYPES = "Word Documents|*.DOC;*.DOCX|Text Documents|*.TXT";

        static DocumentAssistant() {
            random = new Random();
            o = Missing.Value;
            oFalse = false;
            oTrue = true;

            app = null;
            docs = null;
            doc = null;
        }

        /// <summary>
        /// Allows the user to select a template to generate a new form from, and generates it using the replacements
        /// provided.
        /// </summary>
        /// <param name="replacements">The replacements to use when generating from the template</param>
        public static void SelectAndGenerate(Dictionary<string, string> replacements) {

            // Create an instance of the open file dialog box.
            OpenFileDialog openDatabaseFileDialog = new OpenFileDialog();

            // Set filter options and filter index.
            openDatabaseFileDialog.Filter = DOC_TYPES;
            openDatabaseFileDialog.FilterIndex = 1;

            // Process input if the user clicked OK.
            if (openDatabaseFileDialog.ShowDialog() == DialogResult.OK) {
                //Generate the form
                GenerateAgreement(openDatabaseFileDialog.FileName, replacements);
            }

        }

        /// <summary>
        /// Generates a form from a template by replacing all occurances of each token with their value.
        /// The generated form is then displayed to the user in a Word Document.
        ///
        /// </summary>
        /// <param name="templatePath">The path to the document to use as a template</param>
        /// <param name="replacements">A set of key value pairs, where the keys are tokens and the values are what the
        /// tokens should be replaced with.</param>
        public static void GenerateAgreement(string templatePath, Dictionary<string, string> replacements) {
            //set document path
            object path = CreateTempFile(templatePath);
            try {
                //Open Microsoft Word
                app = new Word.Application();
                app.Visible = false;
                app.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;
                //Open the document
                docs = app.Documents;
                doc = docs.Open(ref path, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o);
                doc.Activate();

                //Replace each key, with it's associated value
                foreach (KeyValuePair<string, string> replacement in replacements) {
                    foreach (Word.Range range in doc.StoryRanges) {
                        Word.Find find = range.Find;
                        //set text to find and text to replace it with
                        //  e.g. Key = <[[CITY]]> and Value = "Canberra"
                        object findText = replacement.Key;
                        object replacText = replacement.Value;
                        object replace = Word.WdReplace.wdReplaceAll;
                        object findWrap = Word.WdFindWrap.wdFindContinue;

                        find.Execute(ref findText, ref o, ref o, ref o, ref oFalse, ref o,
                            ref o, ref findWrap, ref o, ref replacText,
                            ref replace, ref o, ref o, ref o, ref o);

                        Marshal.FinalReleaseComObject(find);
                        Marshal.FinalReleaseComObject(range);
                    }
                }

                doc.Save();
                //The temporary document has been generated and saved, show it in Word.
                app.Visible = true;
                //((Word._Document)doc).Close(ref o, ref o, ref o);
                //app.Quit(ref o, ref o, ref o);
            } finally {
                if (doc != null)
                    Marshal.FinalReleaseComObject(doc);

                if (docs != null)
                    Marshal.FinalReleaseComObject(docs);

                if (app != null)
                    Marshal.FinalReleaseComObject(app);
            }
        }

        /// <summary>
        /// Creates a temporary version of an existing file, in the system's designated temporary file path.
        /// The temp file is given the prefix 'tmp######' where ###### is any random integer.
        /// 
        /// These temporary files are used during template generation to avoid modifying the original.
        /// </summary>
        /// <param name="pathToOriginal">The file to copy</param>
        /// <returns>The path to the temporary version of the copied file</returns>
        public static string CreateTempFile(string pathToOriginal) {
            //create a temporary file name
            string tmpFileName = "tmp" + random.Next().ToString() + Path.GetFileName(pathToOriginal);
            //get the path to the temporary folder
            string tmpFileLocation = Path.GetTempPath();
            //create the full path to the tmp file
            string tmpFullPath = Path.Combine(tmpFileLocation, tmpFileName);

            //copy the original file to the new tmp path
            File.Copy(pathToOriginal, tmpFullPath);

            //return the tmp file's path
            return tmpFullPath;
        }
    }
}
